package com.wy.interceptor;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.web.servlet.config.annotation.InterceptorRegistration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;


/**
 *
 * 此类是通过spring.factories加载的
 *
 * 解析注解
 * 1.通过实现ApplicationContextAware接口得到applicationContext
 * 2.从applicationContext中得到含有Interceptor注解的bean
 * 3.实现WebMvcConfigurer接口，根据注解中的参数添加拦截器。
 * 4.根据注解中的参数进行拦截器的排序
 * 5.如果有ignore参数，自定义拦截器，判断是否需要拦截如果不需要拦截，则放掉。
 */
public class InterceptHanlder implements WebMvcConfigurer, ApplicationContextAware {

    private ApplicationContext context;
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        String[] beanNames = context.getBeanNamesForAnnotation(Interceptor.class);
        List<HandlerInterceptorAdapter> interceptors = Arrays.stream(beanNames).map(bean -> context
                .getBean(bean, HandlerInterceptorAdapter.class)).sorted((o1, o2) -> {
            Interceptor c1 = o1.getClass().getAnnotation(Interceptor.class);
            Interceptor c2 = o2.getClass().getAnnotation(Interceptor.class);
            return c1.order() - c2.order();
        }).collect(Collectors.toList());

        interceptors.forEach(interceptor->{
            InterceptorRegistration registration = registry.addInterceptor(interceptor);
            Interceptor annotation = interceptor.getClass().getAnnotation(Interceptor.class);
            registration.addPathPatterns(annotation.pathPatterns());
            registration.excludePathPatterns(annotation.excludePatterns());
        });
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.context = applicationContext;
    }

}
